package cc.rengu.igas.cops.core.service.trans.payment;


import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.core.service.base.ManageService;
import cc.rengu.igas.cops.facade.request.PayOrderCloseRequest;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.GlobalTransUtil;
import com.alibaba.fastjson.JSON;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 支付订单关闭
 * Created by LS on 2020/8/14.
 */
public class CopsPayOrderCloseService extends ManageService implements TransCustomImpl {

    @Override
    protected Object bizBeforeCust() throws Exception {
        PayOrderCloseRequest payOrderCloseRequest = new PayOrderCloseRequest();
        ConvertUtil.convertOutput(payOrderCloseRequest);
        return payOrderCloseRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        PayOrderCloseRequest payOrderCloseRequest = (PayOrderCloseRequest) request;
        String instId = payOrderCloseRequest.getHeader().getInstId();
        String userOrderId = payOrderCloseRequest.getUserOrderId();
        BizResponse bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);

        //获取订单信息
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, userOrderId);
        if (null == orderInfo) {
            rglog.error("订单信息不存在！");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        List<PayOrderInfo> payOrderInfoList = orderInfo.getPayOrderInfoList();

        /* 过滤实时入账的支付订单 */
        Predicate<PayOrderInfo> d0Filter1 = p -> !ShareParamConstant.SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
        Predicate<PayOrderInfo> d0Filter2 = p -> !ShareParamConstant.OTHER_SUB_SYS_ID_D0_REALTIME.equals(p.getChannelBizType());
        payOrderInfoList = payOrderInfoList.stream().filter(d0Filter1.and(d0Filter2))
                .sorted(Comparator.comparing(PayOrderInfo::getDstCallIndex)).collect(Collectors.toList());
        /* 获取主体支付方 */
        Predicate<PayOrderInfo> acctFilter = p -> !ChannelEnum.ACCT.getChannelType().equals(p.getMsgDstId());
        Predicate<PayOrderInfo> mompFilter = p -> !ChannelEnum.MOMP.getChannelType().equals(p.getMsgDstId());
        List<PayOrderInfo> payOrderInfoListFilter = payOrderInfoList.stream().filter(acctFilter.and(mompFilter)).collect(Collectors.toList());
        if (payOrderInfoListFilter.isEmpty()) {
            rglog.debug("用户订单未支付,直接更新订单状态为关闭!", instId, userOrderInfo.getSysSeqNum());
            userOrderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
                rglog.info("更新用户订单表订单状态为关闭失败:{}", JSON.toJSONString(userOrderInfo));
                throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
            }
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return bizResponse;
        }
        /* 判断是否存在商户D0实时入账的流水 */
        payOrderInfoListFilter = payOrderInfoListFilter.stream().filter(item -> !"D0".equals(item.getDstChannelType())).collect(Collectors.toList());
        if (payOrderInfoListFilter.size() > 1) {
            rglog.info("当前交易存在多种主支付方式，请排查是否存在主支付方式过滤问题!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        PayOrderInfo payOrderInfo = payOrderInfoListFilter.get(0);
        GlobalTransUtil.setCacheValue(TransCacheConstant.PAY_ORDER_INFO, payOrderInfo);

        //订单状态
        String orderState = userOrderInfo.getOrderStatus();
        //交易状态
        String orderTransState = userOrderInfo.getTransStatus();
        if (OrderStatusEnum.CLOSE.getStatus().equals(orderState)) {
            rglog.info("用户订单已关闭.orderStatus:<{}>", orderState);
            throw new BizException(RespCodeEnum.ORDER_CLOSED.getRespCode(), RespCodeEnum.ORDER_CLOSED.getRespDesc());
        }
        if (OrderStatusEnum.FINISH.getStatus().equals(orderState)) {
            rglog.info("用户订单已完成.orderStatus:<{}>", orderState);
            throw new BizException(RespCodeEnum.ORDER_FINISH.getRespCode(), RespCodeEnum.ORDER_FINISH.getRespDesc());
        }
        //已过期或新建订单
        if (OrderStatusEnum.INVALID.getStatus().equals(orderState) || OrderStatusEnum.INIT.getStatus().equals(orderState)) {
            //订单交易状态明确失败订单可直接关闭
            if (TransStatusEnum.SYSTEM_REJECT.getStatus().equals(orderTransState)) {
                rglog.info("该订单交易状态失败，直接更新订单状态为关闭。transStatus:<{}>", orderTransState);
                userOrderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
                userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
                    rglog.info("更新用户订单表订单状态为关闭失败:{}", JSON.toJSONString(userOrderInfo));
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                }
                bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
                return bizResponse;
            }

            //调用通道接口
            if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
                rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
                throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
            }
            List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                    item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
            ChannelCallCfg channelCallCfg = channelCallSceneDiscern(payOrderCloseRequest, channelCallCfgList);
            Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
            ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
            channelBaseService.callService(txnInfo, orderInfo, channelCallCfg.getBizScene(), request);

            //更新订单为关闭
            userOrderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
                rglog.error("更新用户订单表/营销支付订单表失败");
                throw new BizException(OltpRpcdEnum.OLTP_PROCESS_ERROR);
            }

            //组装应答结果
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return bizResponse;
        } else {
            rglog.info("订单无法关闭，orderStatus:<{}>,transStatus:<{}>", userOrderInfo.getOrderStatus(), userOrderInfo.getTransStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_CLOSE.getRespCode(), RespCodeEnum.ORDER_CANT_CLOSE.getRespDesc());
        }
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {

    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt;
        PayOrderInfo payOrderInfo = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.PAY_ORDER_INFO);
        if (null != payOrderInfo) {
            if (ChannelEnum.UPWX.getChannelType().equals(payOrderInfo.getMsgDstId()) ||
                    ChannelEnum.NUWX.getChannelType().equals(payOrderInfo.getMsgDstId()) ||
                    ChannelEnum.WXZF.getChannelType().equals(payOrderInfo.getMsgDstId())) {
                //微信支付订单关闭场景
                channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).findFirst();
            } else if (ChannelEnum.UPAL.getChannelType().equals(payOrderInfo.getMsgDstId()) ||
                    ChannelEnum.NUAL.getChannelType().equals(payOrderInfo.getMsgDstId()) ||
                    ChannelEnum.ALIP.getChannelType().equals(payOrderInfo.getMsgDstId())) {
                //支付宝支付订单关闭场景
                channelCallCfgOpt = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).findFirst();
            } else {
                rglog.error("未知道的通道类型:{}", payOrderInfo.getMsgDstId());
                return null;
            }
        } else {
            rglog.error("获取不到支付订单信息，未知调用通道!");
            return null;
        }
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        if (ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())) {
            List<PayOrderInfo> payOrderInfoList = orderInfo.getPayOrderInfoList();
            //获订单支付时未调用营销，则交易结束，不再向营销模块发起营销冲正
            if (payOrderInfoList.stream().noneMatch(item -> item.getMsgDstId().equals(ChannelEnum.MOMP.getChannelType()))) {
                return CheckResultEnum.FINISH;
            }
        }
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
